home *** CD-ROM | disk | FTP | other *** search
/ Turnbull China Bikeride / Turnbull China Bikeride - Disc 2.iso / BARNET / FREENET / MELL / NETLIB00 / NetLib / s / gettime < prev    next >
Text File  |  1995-08-19  |  6KB  |  198 lines

  1. ; ----------------------------------------------------------------------
  2. ; Copyright Adam Goodfellow 1994, all rights reserved.
  3. ;
  4. ; Fast ARM code implementation of unix gettimeofday(2) function.
  5. ;
  6. ; C structures and function prototype:
  7. ;
  8. ; struct timeval {
  9. ;     long    tv_sec;        /* seconds */
  10. ;     long    tv_usec;    /* and microseconds */
  11. ; };
  12. ; struct timezone {
  13. ;     int    tz_minuteswest;    /* minutes west of Greenwich */
  14. ;     int    tz_dsttime;    /* type of dst correction */
  15. ; };
  16. ;
  17. ; int gettimeofday(struct timeval *tv, struct timezone *tz);
  18. ;
  19.  
  20. IOC_Base    EQU    &3200000
  21. IOC_T0CountLow    EQU    &40
  22. IOC_T0CountHigh    EQU    &44
  23. IOC_T0LatchLow    EQU    &40
  24. IOC_T0LatchHigh    EQU    &44
  25. IOC_T0GoCommand    EQU    &48
  26. IOC_T0GetCount    EQU    &4C
  27.  
  28. XOS_EnterOS    EQU    &020016
  29. XOS_Word    EQU    &020007
  30.  
  31. r0        RN    0
  32. r1        RN    1
  33. r2        RN    2
  34. r3        RN    3
  35. r4        RN    4
  36. r5        RN    5
  37. r6        RN    6
  38. r7        RN    7
  39. r8        RN    8
  40. r9        RN    9
  41. r10        RN    10
  42. r11        RN    11
  43. r12        RN    12
  44. r13        RN    13
  45. r14        RN    14
  46. r15        RN    15
  47. sp        RN    13
  48. lr        RN    14
  49. pc        RN    15
  50. psr        RN    15
  51.  
  52. i_flag        EQU    &08000000
  53. svc_mode    EQU    &00000003
  54.  
  55.         AREA    |C$$code|,CODE,READONLY
  56.  
  57. r_s        RN    0    ;seconds
  58. r_u        RN    1    ;micro seconds
  59. r_a        RN    2    ;LS 32 bits of 40bit Risc OS time of day
  60. r_b        RN    3    ;MS 8 bits of 40bit Risc OS time of day
  61. r_c        RN    4    ;1/2 micro-secs read for IOC timer 0
  62. r_p        RN    5    ;Temp reg }
  63. r_t        RN    6    ;Temp reg } On of these is not needed
  64. r_v        RN    7    ;Temp reg }
  65. r_tv        RN    8    ;struct timeval *tv, or NULL
  66. r_tz        RN    9    ;struct timezone *tz, or NULL
  67.  
  68. ;Uses 8 bytes of stack for temp space
  69. ;    44 bytes for register storage.
  70. ;    could be reduced to 28 by fiddling temp regs and not saving r0-r3
  71. ;
  72.  
  73. ; -------------------------------------------------------------------------
  74. ; Read time of day and us from IOC timer 0
  75. ;
  76. ;On entry:
  77. ;  R0 = pointer to buffer for timeval struct
  78. ;  R1 = pointer to buffer for timezone struct
  79. ;
  80.             EXPORT    gettimeofday
  81. gettimeofday
  82.             STMFD    sp!, {r0-r9, lr}
  83.  
  84.             MOV    r_tz, r1
  85.             MOVS    r_tv, r0            ;timeval wanted?
  86.             BEQ    tod_tz                ;no - straight to timezone
  87.  
  88.             SUB    sp, sp, #8
  89.             MOV    r1, sp                ;Take SP here as wont be avilable later
  90.  
  91.             MOV    r_p, psr            ;Keep PSR from current processor mode
  92.             SWI    XOS_EnterOS
  93.             TEQP    psr, #(i_flag :OR: svc_mode)    ;Disable IRQs, stay in SVC mode
  94.  
  95.             MOV    r_a, #IOC_Base            ;Read IOC timer 0 value
  96.             STRB    r_a, [r_a, #IOC_T0GetCount]
  97.             LDRB    r_b, [r_a, #IOC_T0LatchLow]
  98.             LDRB    r_c, [r_a, #IOC_T0LatchHigh]
  99.             ORR    r_b, r_b, r_c, LSL #8
  100.             MOV    r_a, #&4e00            ;20000-n
  101.             ORR    r_a, r_a, #&20
  102.             SUB    r_b, r_a, r_b
  103.  
  104.             MOV    r0, #3                ;Get real time while IRQs still
  105.             STRB    r0, [r1, #0]            ;disabled to stop it ticking over
  106.             MOV    r0, #14                ;Returns 40 bit binary
  107.             SWI    XOS_Word
  108.  
  109.             TEQP    psr, r_p            ;Back to processor mode and IRQ state on entry
  110.             MOV    r_p, r_p
  111.  
  112.             LDMIA    sp!, {r_a, r_b}            ;t[4]...t[0] are bytes in r_a and r_b
  113.             AND    r_b, r_b, #&ff            ;Just want one byte from r_b
  114.  
  115. ; r_a, r_b = Real time,  r_c counter time (micro secs)
  116. ; ----------
  117.             LDR    r_v, =&6e996a00            ;To Unix and C time range
  118.             SUBS    r_a, r_a, r_v            ;5 byte time - 0x336e996a00
  119.             SBC    r_b, r_b, #&33            ;Risc OS time of 1st Jan 1970
  120.  
  121. ; ----------
  122. ; r_t is a temp,  r_v is a temp,  r_u is usecs,  r_s is secs
  123.  
  124. ; The following is a 40 bit div/mod by 100
  125.  
  126.             MOV    r_s, #0                ;tv->tv_sec = 0
  127.             MOV    r_u, #0                ;tv->tv_usec = 0
  128.  
  129.             MOV    r_t, r_b            ;t[4]
  130.             ORR    r_u, r_t, r_u, LSL #8        ;tv->tv_usec = (tv->tv_usec<<8) | t[4];
  131.             CMP    r_u, #100            ;if (tv->tv_usec>=100)
  132.             BLGE    divmod100            ;  tv->tv_usec = tv->tv_usec % 100;
  133.             ORRGE    r_s, r_t, r_s, LSL #8        ;  tv->tv_sec = (tv->tv_sec<<8) | (tv->tv_usec/100);
  134.  
  135.             MOV    r_t, r_a, LSR #24        ;t[3]
  136.             ORR    r_u, r_t, r_u, LSL #8        ;tv->tv_usec = (tv->tv_usec<<8) | t[4];
  137.             CMP    r_u, #100            ;if (tv->tv_usec>=100)
  138.             BLGE    divmod100            ;  tv->tv_usec = tv->tv_usec % 100;
  139.             ORRGE    r_s, r_t, r_s, LSL #8        ;  tv->tv_sec = (tv->tv_sec<<8) | (tv->tv_usec/100);
  140.  
  141.             MOV    r_t, r_a, LSR #16
  142.             AND    r_t, r_t, #&ff            ;t[2]
  143.             ORR    r_u, r_t, r_u, LSL #8        ;tv->tv_usec = (tv->tv_usec<<8) | t[4];
  144.             CMP    r_u, #100            ;if (tv->tv_usec>=100)
  145.             BLGE    divmod100            ;  tv->tv_usec = tv->tv_usec % 100;
  146.             ORRGE    r_s, r_t, r_s, LSL #8        ;  tv->tv_sec = (tv->tv_sec<<8) | (tv->tv_usec/100);
  147.  
  148.             MOV    r_t, r_a, LSR #8
  149.             AND    r_t, r_t, #&ff            ;t[1]
  150.             ORR    r_u, r_t, r_u, LSL #8        ;tv->tv_usec = (tv->tv_usec<<8) | t[4];
  151.             CMP    r_u, #100            ;if (tv->tv_usec>=100)
  152.             BLGE    divmod100            ;  tv->tv_usec = tv->tv_usec % 100;
  153.             ORRGE    r_s, r_t, r_s, LSL #8        ;  tv->tv_sec = (tv->tv_sec<<8) | (tv->tv_usec/100);
  154.  
  155.             MOV    r_t, r_a
  156.             AND    r_t, r_t, #&ff            ;t[0]
  157.             ORR    r_u, r_t, r_u, LSL #8        ;tv->tv_usec = (tv->tv_usec<<8) | t[4];
  158.             CMP    r_u, #100            ;if (tv->tv_usec>=100)
  159.             BLGE    divmod100            ;  tv->tv_usec = tv->tv_usec % 100;
  160.             ORRGE    r_s, r_t, r_s, LSL #8        ;  tv->tv_sec = (tv->tv_sec<<8) | (tv->tv_usec/100);
  161.  
  162.             RSB    r_t, r_u, r_u, LSL #7        ;cs x 10000 to get usecs
  163.             SUB    r_u, r_t, r_u, LSL #1
  164.             ADD    r_u, r_u, r_u, LSL #2
  165.             MOV    r_u, r_u, LSL #4
  166.  
  167.             ADD    r_u, r_u, r_c, LSR #1        ;Add in usecs/2 from IOC Timer
  168.  
  169.             STMIA    r_tv, {r_s, r_u}        ;Write to timeval struct
  170.  
  171. tod_tz            TEQ    r_tz, #0            ;Optionally write time zone (zero for now)
  172.             MOVNE    r_s, #0
  173.             MOVNE    r_u, #0
  174.             STMNEIA    r_tz, {r_s, r_u}
  175.  
  176.             LDMFD    sp!, {r0-r9, pc}^
  177.  
  178. ; ----------
  179. ; Highly optimised 16 bit div/mod 100
  180. ; could inline this with conditionals to give constant execution time.
  181. divmod100
  182.             MOV    r_v, r_u, LSR #1              ;Divide by 100 to get seconds
  183.             RSB    r_v, r_v, r_v, LSL #3
  184.             RSB    r_v, r_v, r_v, LSL #3
  185.             RSB    r_t, r_v, r_v, LSL #7
  186.             ADD    r_v, r_v, r_v, LSL #2
  187.             SUB    r_v, r_t, r_v, LSL #2
  188.             MOV    r_t, r_v, LSR #18        ;result in r_t
  189.  
  190.             ADD    r_v, r_t, r_t, LSL #2          ;Remainder of division (0-99)
  191.             ADD    r_v, r_v, r_v, LSL #2
  192.             SUB    r_u, r_u, r_v, LSL #2        ;remainder back in r_u
  193.  
  194.             MOVS    pc, lr
  195.  
  196.     END
  197.